home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr26
/
netprog.zip
/
NETPROG.TAR
/
lib
/
dgsendrecv.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-17
|
3KB
|
114 lines
/*
* Send a datagram to a server, and read a response.
* Establish a timer and resend as necessary.
* This function is intended for those applications that send a datagram
* and expect a response.
* Returns actual size of received datagram, or -1 if error or no response.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <signal.h>
extern int errno;
#include "rtt.h" /* our header for RTT calculations */
static struct rtt_struct rttinfo; /* used by rtt_XXX() functions */
static int rttfirst = 1;
static int tout_flag; /* used in this file only */
int
dgsendrecv(fd, outbuff, outbytes, inbuff, inbytes, destaddr, destlen)
int fd; /* datagram socket */
char *outbuff; /* pointer to buffer to send */
int outbytes; /* #bytes to send */
char *inbuff; /* pointer to buffer to receive into */
int inbytes; /* max #bytes to receive */
struct sockaddr *destaddr; /* destination address */
/* can be 0, if datagram socket is connect'ed */
int destlen; /* sizeof(destaddr) */
{
int n;
int to_alarm(); /* our alarm() signal handler */
if (rttfirst == 1) {
rtt_init(&rttinfo); /* initialize first time we're called */
rttfirst = 0;
}
rtt_newpack(&rttinfo); /* initialize for new packet */
rexmit:
/*
* Send the datagram.
*/
if (sendto(fd, outbuff, outbytes, 0, destaddr, destlen) != outbytes) {
err_ret("dgsendrecv: sendto error on socket");
return(-1);
}
signal(SIGALRM, to_alarm);
tout_flag = 0; /* for signal handler */
alarm(rtt_start(&rttinfo)); /* calc timeout value & start timer */
n = recvfrom(fd, inbuff, inbytes, 0,
(struct sockaddr *) 0, (int *) 0);
if (n < 0) {
if (tout_flag) {
/*
* The recvfrom() above timed out.
* See if we've retransmitted enough, and
* if so quit, otherwise try again.
*/
if (rtt_timeout(&rttinfo) < 0) {
#ifdef DEBUG
err_ret("dgsendrecv: no response from server");
#endif
rttfirst = 1; /* reinit if called again */
return(-1);
/* errno will be EINTR */
}
/*
* We have to send the datagram again.
*/
errno = 0; /* clear the error flag */
#ifdef DEBUG
err_ret("dgsendrecv: timeout, retransmitting");
rtt_d_flag = 1;
rtt_debug(&rttinfo);
#endif
goto rexmit;
} else {
err_ret("dgsendrecv: recvfrom error");
return(-1);
}
}
alarm(0); /* stop signal timer */
rtt_stop(&rttinfo); /* stop RTT timer, calc & store new values */
#ifdef DEBUG
rtt_debug(&rttinfo);
#endif
return(n); /* return size of received datagram */
}
/*
* Signal handler for timeouts (SIGALRM).
* This function is called when the alarm() value that was set counts
* down to zero. This indicates that we haven't received a response
* from the server to the last datagram we sent.
* All we do is set a flag and return from the signal handler.
* The occurrence of the signal interrupts the recvfrom() system call
* (errno = EINTR) above, and we then check the tout_flag flag.
*/
to_alarm()
{
tout_flag = 1; /* set flag for function above */
}